{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 在测试视频(OpenCV安装目录\\sources\\samples\\data)上，使用基于混合高斯模型的背景提取算法，提取前景并显示(显示二值化图像，前景为白色)。\n",
    "# 2. 在1基础上，将前景目标进行分割，进一步使用不同颜色矩形框标记，并在命令行窗口中输出每个矩形框的位置和大小。\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "cap = cv2.VideoCapture(\"..\\\\images\\\\vtest.avi\")\n",
    "fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows=False)\n",
    "\n",
    "# 生成随机颜色条\n",
    "color_label = np.random.randint(0, 255, (100, 3))\n",
    "\n",
    "area_thresh = 200\n",
    "frame_number = 1\n",
    "while True:\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:  # 没有读到当前帧\n",
    "        break\n",
    "    fgmask = fgbg.apply(frame)  # 获取前景\n",
    "    bgmask = fgbg.getBackgroundImage()  # 获取背景\n",
    "\n",
    "    cv2.imshow('fgmask', fgmask)\n",
    "    cv2.imshow('bgmask', bgmask)\n",
    "    # 以下代码为检测目标\n",
    "    _, fgmask = cv2.threshold(fgmask, 30, 0xff, cv2.THRESH_BINARY)\n",
    "    cnts = cv2.findContours(fgmask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "    count = 0\n",
    "    for c in cnts[1]:\n",
    "        area = cv2.contourArea(c)\n",
    "        if area < area_thresh:\n",
    "            continue\n",
    "        count += 1\n",
    "        x, y, w, h = cv2.boundingRect(c)\n",
    "        cv2.rectangle(frame, (x, y), (x+w, y+h), color_label[np.random.randint(0, 100)].tolist(), 2)\n",
    "        print(\"第{}帧的第{}目标，位置：({},{}), 大小：{}\".format(frame_number, count, x, y, w*h))\n",
    "    print(\"第{}帧检测结束，一共检测到{}目标\".format(frame_number, count))\n",
    "    frame_number += 1\n",
    "    cv2.imshow(\"source\", frame)\n",
    "    # 检测目标代码结束\n",
    "    k = cv2.waitKey(10) & 0xff\n",
    "    if k == 27:\n",
    "        break\n",
    "\n",
    "cap.release()\n",
    "cv2.destroyAllWindows()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. 使用光流估计方法，在前述测试视频上计算特征点，进一步进行特征点光流估计。\n",
    "\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "cap = cv2.VideoCapture(\"..\\\\images\\\\vtest.avi\")\n",
    "\n",
    "# 角点检测所需参数,在进行光流估计计算之前，需要先进行角点检测，然后再把检测出的特征点进行光流估计。\n",
    "# 第一个参数输入图像，maxCorners：角点最大数量（效率），qualityLevel：品质因子（特征值越大的越好，来筛选）\n",
    "#                    minDistance：距离，相当于这区间有比这个角点强的，就不要这个弱的了\n",
    "feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7)\n",
    "# lucas kanade参数\n",
    "lk_params = dict(winSize=(15, 15), maxLevel=2)\n",
    "\n",
    "# 拿到第一帧图像，这里没有循环。\n",
    "ret, old_frame = cap.read()\n",
    "old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)\n",
    "\n",
    "# 不使用掩膜，在整幅图像上寻找特征点\n",
    "P0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)\n",
    "while True:\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:\n",
    "        break\n",
    "    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n",
    "    # 基于上一张图像、本张图像、上一张图像的关键点计算光流\n",
    "    P1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, gray, P0, None, **lk_params)\n",
    "\n",
    "    # 选取好的跟踪点\n",
    "    goodPoints = P1[st == 1]\n",
    "    goodOldPoints = P0[st == 1]\n",
    "    #\n",
    "    res = frame.copy()\n",
    "    drawColor = (0, 0, 255)\n",
    "    for i, (cur, prev) in enumerate(zip(goodPoints, goodOldPoints)):\n",
    "        x0, y0 = cur.ravel()\n",
    "        x1, y1 = prev.ravel()\n",
    "        cv2.line(res, (x0, y0), (x1, y1), drawColor)\n",
    "        cv2.circle(res, (x0, y0), 3, drawColor)\n",
    "    old_gray = gray.copy()\n",
    "    P0 = goodPoints.reshape(-1, 1, 2)\n",
    "\n",
    "    # 显示结果\n",
    "    cv2.imshow(\"检测结果\", res)\n",
    "    k = cv2.waitKey(30) & 0xff\n",
    "    if k == 27:\n",
    "        break\n",
    "\n",
    "cap.release()\n",
    "cv2.destroyAllWindows()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
